class Vue {
  constructor(options) {
    this.$el = options.$el
    this._data = options.data
    this.$data = this._data

    new Observe(this._data)
  }
}

class Observe {
  constructor(data) {
    if (typeof data === 'object') {
      this.walk(data)
    }
  }
  walk(data) {
    let dataKeys = Object.keys(data) || []
    for (let i = 0; i < dataKeys.length; i++) {
      this.defineReactive(data, dataKeys[i])
    }
  }
  defineReactive(obj, key) {
    if (typeof obj[key] === 'object') {
      this.walk(obj[key])
    }

    const dep = new Dep()
    let val = obj[key]

    Object.defineProperty(obj, key, {
      enumerable: true,
      configurable: true,
      get() {
        if (Dep.target) {
          dep.addSub(Dep.target)
        }
        return val
      },
      set(newVal) {
        val = newVal
        // 依赖的变更
        dep.notify(newVal)
      },
    })
  }
}

class Dep {
  constructor() {
    this.subs = []
  }
  addSub(watcher) {
    this.subs.push(watcher)
  }
  notify(newVal) {
    for (let i = 0; i < this.subs.length; i++) {
      this.subs[i].update(newVal)
    }
  }
}
Dep.target = null

let uid = 0
class Watcher {
  constructor(vm, key, cb) {
    this.vm = vm
    this.uid = uid++
    this.cb = cb

    Dep.target = this
    this.value = vm.$data[key]

    // this.deps = []
  }
  update(newValue) {
    if (this.value !== newValue) {
      this.value = newValue
      this.run()
    }
  }
  run() {
    this.cb(this.value)
  }
}

let app = new Vue({
  el: '#app',
  data: {
    name: 'zhen',
    message: 'hello vue',
  },
})

new Watcher(app, 'message', (value) => {
  console.log('message 引起的dom变更--->', value)
})
new Watcher(app, 'name', (value) => {
  console.log('name 引起的dom变更--->', value)
})
// console.log(22, app.message)
app.$data.message = 'hello hello'
